package maxEntClassifier;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;

import opennlp.model.DataIndexer;
import opennlp.model.MutableContext;
import featureSelection.KeyValuePair;

public class U {

	public static int getIndex(String[] sa, String s) {
		for (int i = 0; i < sa.length; i++) {
			if (sa[i].equals(s))
				return i;
		}
		return -1;
	}

	public static double minOr0(double[] da) {
		double res = 0;
		for (int i = 0; i < da.length; i++) {
			if (da[i] < res)
				res = da[i];
		}
		return res;
	}

	public static void main(String[] args) {

		

	}

	public static double getFeatureCHI() {

		double p = 0.4;
		double r = 0.8;
		double n = 200;
		double n_1 = 1;
		double n11 = n_1 * r;
		double n1_ = n11 / p;
		double n10 = n1_ - n11;
		double n01 = n_1 - n11;
		double n00 = n + n11 - n10 - n01;

		double n0_ = 200 - n1_;
		double n_0 = 200 - n_1;
		if (n00 < 0 || n01 < 0 || n10 < 0 || n11 <= 0 || n_0 < 0 || n0_ < 0
				|| n1_ < 0 || n_1 < 0) {
			System.err.println("featureStore fail!");
			System.exit(-1);
		}
		double e11 = n1_ * n_1 / n;
		double e10 = n1_ * n_0 / n;
		double e01 = n0_ * n_1 / n;
		double e00 = n0_ * n_0 / n;

		double res = Math.pow(n11 - e11, 2) / e11 + Math.pow(n10 - e10, 2)
				/ e10 + Math.pow(n01 - e01, 2) / e01 + Math.pow(n00 - e00, 2)
				/ e00;

		return res;
	}

	public static boolean isIn(int[] ia, int content) {
		for (int i = 0; i < ia.length; i++) {
			if (content == ia[i])
				return true;
		}
		return false;
	}

	public static BufferedReader getReader(String file)
			throws FileNotFoundException {
		return new BufferedReader(new FileReader(file));
	}

	public static BufferedWriter getWriter(String file) throws IOException {
		return new BufferedWriter(new FileWriter(file));
	}

	public static String destop = "./../../";

	public static String getWordStringFromFile(File f) throws IOException {
		HashSet<String> hs = new HashSet<String>();
		String content = U.getFileContent(f);
		content = content.replaceAll("<.+?>", " ");
		String[] sa = content.split(" ");
		for (String s : sa) {
			s = preProcessWord(s);
			if (s != null)
				hs.add(s);
		}

		String res = "";
		for (String w : hs) {
			res += w + " ";
		}
		return res;
	}

	public static String preProcessWord(String w) {
		if (w.length() > 20)
			return null;
		if (isDigit(w))
			return null;
		w = w.toLowerCase();
		int begin, end;
		for (begin = 0; begin < w.length()
				&& !Character.isLetter(w.charAt(begin)); begin++)
			;
		if (begin == w.length())
			return null;
		for (end = w.length() - 1; end >= 0
				&& !Character.isLetter(w.charAt(end)); end--)
			;
		if (end == -1)
			return null;

		return w.substring(begin, end + 1);
	}

	static boolean isDigit(String value) {
		try {
			Double.parseDouble(value);
			return true;
		} catch (NumberFormatException e) {
			return false;
		}
	}

	static double truncation(double d) {
		int _d = (int) (d * 100);
		return ((double) _d) / 100;
	}

	static void transferDir2MaxentSet(String dir, String out)
			throws IOException {
		BufferedWriter bw = new BufferedWriter(new FileWriter(out));
		File[] dirs = new File(dir).listFiles();
		String className;
		for (File d : dirs) {
			className = d.getName();
			File[] files = d.listFiles();
			for (File f : files) {
				bw.write(getWordStringFromFile(f) + className + "\n");
			}
		}
		bw.close();
	}

	@SuppressWarnings("unchecked")
	public static void sort(ArrayList<KeyValuePair> list) {
		// sort the features according to conditional probability
		Comparator comp = new Comparator() {
			public int compare(Object o1, Object o2) {
				KeyValuePair p1 = (KeyValuePair) o1;
				KeyValuePair p2 = (KeyValuePair) o2;
				if (p1.value < p2.value)
					return 1;
				else
					return 0;
			}
		};
		Collections.sort(list, comp);
	}

	public static void add1(HashMap<String, Integer> m, String s) {
		int i = 0;
		if (null != m.get(s))
			i = m.get(s);
		m.put(s, i + 1);
	}

	public static void add1(Hashtable<String, Integer> m, String s) {
		int i = 0;
		if (null != m.get(s))
			i = m.get(s);
		m.put(s, i + 1);
	}

	public static double getExpectation(Vector<Double> v) {
		double result = 0;
		for (int i = 0; i < v.size(); i++) {
			result += v.get(i);
		}
		return result / v.size();
	}

	public static double getSD(Vector<Double> v) {
		double e = getExpectation(v);
		double result = 0;
		for (int i = 0; i < v.size(); i++) {
			result += (v.get(i) - e) * (v.get(i) - e);
		}
		return Math.sqrt(result / (v.size() - 1));
	}

	public static double relatedCoefficient(Vector<Double> v, Vector<Double> v2) {

		double res = 0;
		double e = getExpectation(v);
		double e2 = getExpectation(v2);
		for (int i = 0; i < v.size(); i++) {
			res += (v.get(i) - e) * (v2.get(i) - e2);
		}
		return res / getSD(v) / getSD(v2) / v.size();
	}

	public static int tryGet(HashMap<String, Integer> hm, String s) {
		if (null != hm.get(s))
			return hm.get(s);
		return 0;
	}

	public static int hashtableTryGet(Hashtable<String, Integer> hm, String s) {
		if (null != hm.get(s))
			return hm.get(s);
		return 0;
	}

	public static Hashtable<String, Integer> getFeatureCountFromTrainSet(
			String trainSet) throws IOException {
		Hashtable<String, Integer> featureCountTable = new Hashtable<String, Integer>();

		BufferedReader br = new BufferedReader(new FileReader(trainSet));
		while (true) {
			String line = br.readLine();
			if (null == line || line.trim().equals(""))
				break;
			String[] sa = line.split(" ");
			String trueLabel = sa[sa.length - 1];
			// featureMapping_Str2Int.put(trueLabel, 0);
			for (int i = 0; i < sa.length - 1; i++) {
				U.add1(featureCountTable, sa[i] + ":" + trueLabel);
			}
		}
		return featureCountTable;
	}

	public static Hashtable<String, Integer> getYCountFromTrainSet(
			String trainSet) throws IOException {
		BufferedReader br = new BufferedReader(new FileReader(trainSet));
		Hashtable<String, Integer> yCount = new Hashtable<String, Integer>();
		while (true) {
			String line = br.readLine();
			if (null == line || line.trim().equals(""))
				break;
			U.add1(yCount, line.substring(line.lastIndexOf(" ") + 1, line
					.length()));
		}
		br.close();
		return yCount;

	}

	@SuppressWarnings("unchecked")
	public static Object getProperty(Object owner, String fieldName)
			throws Exception {
		Class ownerClass = owner.getClass();

		Field field = ownerClass.getField(fieldName);

		Object property = field.get(owner);

		return property;
	}

	public static double tryGetD(Hashtable<String, Double> ht, String key) {
		if (null != ht.get(key)) {
			return ht.get(key);
		}
		return 0;
	}
	

	public static float tryGetF(HashMap<String, Float> ht, String key) {
		if (null != ht.get(key)) {
			return ht.get(key);
		}
		return 0;
	}

	public static int tryGet(Hashtable<String, Integer> ht, String key) {
		if (null != ht.get(key)) {
			return ht.get(key);
		}
		return 0;
	}

	public static int tryGetI(Hashtable<String, Integer> ht, String key) {
		if (null != ht.get(key)) {
			return ht.get(key);
		}
		return 0;
	}

	public static class MeasureType {
		public static String featureFMeasure = "featureFMeasure";
		public static String featureMI = "featureMI";
		public static String featureCHI = "featureCHI";
		public static String featurePrecision = "featurePrecision";
		public static String predicateCHI = "predicateCHI";
	}

	public static void maxentTrainSet2svmTrainSet(String maxentTrain,
			String maxentTest, String svmTrain, String svmTest)
			throws IOException {
		BufferedReader br = U.newReader(maxentTrain);

		// map word to index
		HashMap<String, Integer> wordMap = new HashMap<String, Integer>();
		HashMap<String, Integer> labelMap = new HashMap<String, Integer>();
		int wi = 0, li = 0;
		while (true) {
			String line = br.readLine();
			if (null == line || line.trim().equals(""))
				break;
			String[] sa = line.split(" ");
			for (int i = 0; i < sa.length - 1; i++) {
				if (null == wordMap.get(sa[i]))
					wordMap.put(sa[i], wi++);
			}
			if (null == labelMap.get(sa[sa.length - 1]))
				labelMap.put(sa[sa.length - 1], li++);
		}
		br.close();

		// train
		br = U.newReader(maxentTrain);
		BufferedWriter bw = U.newWriter(svmTrain);
		while (true) {
			String line = br.readLine();
			if (null == line || line.trim().equals(""))
				break;
			String[] sa = line.split(" ");
			String res = "" + labelMap.get(sa[sa.length - 1]);

			ArrayList<Integer> al = new ArrayList<Integer>();
			for (int i = 0; i < sa.length - 1; i++)
				al.add(wordMap.get(sa[i]));
			Collections.sort(al);
			for (int i = 0; i < al.size(); i++) {
				res += " " + al.get(i) + ":1";
			}
			bw.write(res + '\n');

		}
		br.close();
		bw.close();

		// test
		br = U.newReader(maxentTest);
		bw = U.newWriter(svmTest);

		while (true) {
			String line = br.readLine();
			if (null == line || line.trim().equals(""))
				break;
			String[] sa = line.split(" ");
			String res = "" + labelMap.get(sa[sa.length - 1]);

			ArrayList<Integer> al = new ArrayList<Integer>();
			for (int i = 0; i < sa.length - 1; i++)
				if (null != wordMap.get(sa[i]))
					al.add(wordMap.get(sa[i]));
			Collections.sort(al);
			for (int i = 0; i < al.size(); i++) {
				res += " " + al.get(i) + ":1";
			}
			bw.write(res + '\n');
		}

		br.close();
		bw.close();
	}

	public static BufferedReader newReader(String file)
			throws FileNotFoundException {
		return new BufferedReader(new FileReader(file));
	}

	public static BufferedWriter newWriter(String file) throws IOException {
		return new BufferedWriter(new FileWriter(file));
	}

	public static void changewebkbFormate(String file, String out)
			throws IOException {
		BufferedReader br = U.getReader(file);
		BufferedWriter bw = U.getWriter(out);
		while (true) {
			String line = br.readLine();
			if (null == line)
				break;
			if (line.trim().equals(""))
				continue;
			int i = line.indexOf('\t');
			bw.write(line.substring(i + 1, line.length()) + " "
					+ line.substring(0, i) + "\n");

		}
		br.close();
		bw.close();

	}

	public static void removeRedundantWord(String f) throws Exception {
		BufferedReader br = U.getReader(f);
		BufferedWriter bw = U.getWriter(f + 1);

		while (true) {
			String line = br.readLine();
			if (line == null || line.equals(""))
				break;
			String[] sa = line.split(" ");
			HashSet<String> s = new HashSet<String>();
			for (int i = 0; i < sa.length - 1; i++) {
				s.add(sa[i]);
			}
			String res = "";
			for (Iterator<String> iterator = s.iterator(); iterator.hasNext();) {
				String string = iterator.next();
				res += string + " ";
			}
			res += sa[sa.length - 1];
			bw.write(res + "\n");
		}

		br.close();
		bw.close();
	}

	public static String getFileContent(File file) throws IOException {
		BufferedReader br = U.getReader(file.getAbsolutePath());
		String res = "";
		while (true) {
			String line = br.readLine();
			if (line == null)
				break;
			line = line.trim();
			if (line.equals(""))
				continue;
			res += " " + line;
		}
		br.close();
		return res;
	}

	public static void everageTrainSet(String in, String out)
			throws IOException {
		int bound = 336;
		BufferedReader r = U.newReader(in);
		BufferedWriter w = U.newWriter(out);
		HashMap<String, Integer> m = new HashMap<String, Integer>();
		m.put("utilities", 10000);
		m.put("healthcare", 10000);
		m.put("energy", 10000);
		while (true) {
			String l = r.readLine();
			if (null == l)
				break;
			String label = l.substring(l.lastIndexOf(" ") + 1, l.length());
			if (U.tryGet(m, label) >= bound)
				continue;
			U.add1(m, label);
			w.write(l + "\n");
		}

		r.close();
		w.close();
	}

	public static String Array2String(Object[] a) {
		String res = "[";
		for (int i = 0; i < a.length; i++) {
			res += " " + a[i];
		}
		return res + " ]";
	}

	public static String Array2String(int[] a) {
		String res = "[";
		for (int i = 0; i < a.length; i++) {
			res += " " + a[i];
		}
		return res + " ]";
	}

	public static String Array2String(double[] a) {
		String res = "[";
		for (int i = 0; i < a.length; i++) {
			res += " " + a[i];
		}
		return res + " ]";
	}

	public static MutableContext[] loadMutableContextArray(HashSet<String> fs,
			DataIndexer di) throws IOException {

		String[] labels = di.getOutcomeLabels();
		String[] predicates = di.getPredLabels();
		MutableContext[] res = new MutableContext[predicates.length];
		for (int i = 0; i < res.length; i++)
			res[i] = new MutableContext(new int[] {}, new double[] {});

		for (String f : fs) {
			int colon = f.lastIndexOf(":");
			int p = U.getIndex(predicates, f.substring(0, colon));
			int l = U.getIndex(labels, f.substring(colon + 1));
			res[p].outcomes = U.arrayAdd(res[p].outcomes, l);
			res[p].parameters = U.arrayAdd(res[p].parameters, 0.0);
		}

		// for(MutableContext mc :res){
		// mc.outcomes=U.sort(mc.outcomes);
		// }
		return res;
	}

	static int[] intSas2A(String s) {
		String[] sa = s.split(" ");
		int[] res = new int[sa.length - 2];
		for (int i = 1; i < sa.length - 1; i++) {
			res[i - 1] = Integer.parseInt(sa[i]);
		}
		return res;
	}

	static double[] doubleSas2A(String s) {
		String[] sa = s.split(" ");
		double[] res = new double[sa.length - 2];
		for (int i = 1; i < sa.length - 1; i++) {
			res[i - 1] = Double.parseDouble(sa[i]);
		}
		return res;
	}

	static void cleanDataSet_removeSingleLabel(String in, String out)
			throws IOException {
		BufferedWriter w = U.newWriter(out);
		BufferedReader r = U.newReader(in);
		while (true) {
			String l = r.readLine();
			l = U.trimBeginAndEnd(l);
			if (null == l)
				break;
			String[] sa = l.split(" ");
			if (sa.length <= 1)
				continue;
			w.write(l + "\n");
		}
		w.close();
		r.close();

	}

	public static String trimBeginAndEnd(String s) {
		if (null == s || s.equals(""))
			return s;
		int i = 0;
		for (; i < s.length() && s.charAt(i) == ' '; i++)
			;
		if (i == s.length())
			return "";
		return s.substring(i).trim();
	}

	public static void saveHashSet(HashSet<String> hs, String f)
			throws IOException {
		BufferedWriter w = U.newWriter(f);
		for (String s : hs) {
			w.write(s + "\n");
		}
		w.close();
	}

	public static HashSet<String> loadHashSet(String f) throws IOException {
		BufferedReader r = U.newReader(f);
		HashSet<String> res = new HashSet<String>();
		while (true) {
			String l = r.readLine();
			if (null == l)
				break;
			res.add(l);
		}
		r.close();
		return res;
	}

	public static int[] arrayAdd(int[] a, int i) {
		int[] res = new int[a.length + 1];
		for (int j = 0; j < a.length; j++) {
			res[j] = a[j];
		}
		res[res.length - 1] = i;
		return res;
	}

	public static double[] arrayAdd(double[] a, double i) {
		double[] res = new double[a.length + 1];
		for (int j = 0; j < a.length; j++) {
			res[j] = a[j];
		}
		res[res.length - 1] = i;
		return res;
	}

	public static int getMaxIndex(int[] a) {
		int max = -Integer.MAX_VALUE;
		int index = -1;
		for (int i = 0; i < a.length; i++) {
			if (a[i] > max) {
				max = a[i];
				index = i;
			}

		}
		return index;
	}

	// ascending order
	public static int[] sort(int[] a) {
		if (a == null)
			return null;
		int[] res = new int[a.length];
		for (int i = res.length - 1; i >= 0; i--) {
			int j = U.getMaxIndex(a);
			res[i] = a[j];
			a[j] = -Integer.MAX_VALUE;
		}
		return res;
	}

	public static void addNoise(String in, String out) throws IOException {
		BufferedReader r = U.newReader(in);
		BufferedWriter w = U.newWriter(out);
		while (true) {
			String l = r.readLine();
			if (l == null)
				break;
			w.write("asfa dd " + l + "\n");
		}
		r.close();
		w.close();
	}

	static void filterDataSet(String in, String s, String b, HashSet<String> set)
			throws IOException {
		BufferedReader r = U.newReader(in);
		BufferedWriter ws = U.newWriter(s);
		BufferedWriter wb = U.newWriter(b);
		while (true) {
			String l = r.readLine();
			if (l == null)
				break;
			String[] sa = l.split(" ");
			String label = sa[sa.length - 1];
			String ss = "";
			boolean isempty = true;
			for (int i = 0; i < sa.length - 1; i++) {
				if (set.contains(sa[i] + ":" + label)) {
					isempty = false;
					ss += sa[i] + " ";
				}
			}
			ss += label;
			if (isempty)
				continue;
			ws.write(ss + "\n");
			wb.write(l + "\n");
		}
		r.close();
		ws.close();
		wb.close();

	}

	public static String getFL(String feature) {
		return feature.substring(feature.lastIndexOf(':') + 1);
	}

	public static String getFP(String feature) {
		return feature.substring(0, feature.lastIndexOf(':'));
	}

	public static HashSet<String> getWordBag(String s) {
		HashSet<String> res = new HashSet<String>();
		String[] sa = s.split(" ");
		for (String ss : sa)
			if (ss != null & ss.length() != 0)
				res.add(ss);
		return res;
	}

	public static void record(String s, String f) {
		BufferedWriter w;
		try {
			w = new BufferedWriter(new FileWriter(f, true));
			w.write(s + "\n");
			w.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public static void saveArrayList(ArrayList<KeyValuePair> al, String f)
			throws IOException {
		BufferedWriter w = newWriter(f);
		for (KeyValuePair kvp : al)
			w.write(kvp.key + "\t" + kvp.value + "\n");
		w.close();
	}

	// "asd sdaf df  ,adf dsf dsf adsf\n")
	public static Vector<String> setMinus(Set<String> set1,
			Set<String> _set2) {
		Vector<String> res = new Vector<String>();
		for (String s1 : set1) {
			if (!_set2.contains(s1))
				res.add(s1);
		}
		return res;
	}

	@SuppressWarnings("unchecked")
	public static void setAdd(Set featureSet, Set featureSet2) {
		for (Object o : featureSet2)
			featureSet.add(o);

	}

	public static double linerTransform(double z, double i, double j, double k,
			double x) {
		if (i >= z) {
			if (x < z || x > i) {
				System.err.println("x is not in the [z,i]");
				System.exit(-1);
			}
		} else {
			if (x < i || x > z) {
				System.err.println("x is not in the [i,z]");
				System.exit(-1);
			}
		}
		return j + (x - z) * (k - j) / (i - z);
	}
	
	public static int power;
	public static double decreaseTransform(double x){
		//form [0,1] to [0,1]
		return Math.pow(x, power);
	}
	
	public static HashSet<String> vector2Set(Vector<String> v){
		HashSet<String> set =new HashSet<String>();
		for(String f:v)
			set.add(f);
		return set;
	}

	public static void changeDataSetToBinary(String in , String out) throws IOException{
		BufferedReader r =U.newReader(in);
		BufferedWriter w =U.newWriter(out);
		while (true) {
			String l =r.readLine();
			if(null==l) break;
			String[] sa =l.split(" ");
			if(sa.length>2){
				for(int i=0;i<sa.length-2;i++)
					l=sa[i]+"@"+sa[i+1]+" "+l;
			}
			w.write(l+"\n");
		}
		r.close();
		w.close();
	}

	public static HashSet<String> vector2HashSet(Vector<String> v) {
		HashSet<String> res =new HashSet<String>();
		for(String f:v)
			res.add(f);
		return res;
	}

	public static String[] set2Sa(Set<String> labels) {
		String[] res=new String[labels.size()];
		int i=0;
		for(String o:labels){
			res[i]=o;
			i++;
		}
		return res;
	}


}
